package com.weilive.core.netty;

import java.net.InetSocketAddress;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public abstract class NettyServer {

	protected static final Logger log = LoggerFactory.getLogger(NettyServer.class);
	
	protected boolean isStart = false;
	protected NettyServerConfig config = new NettyServerConfig();
	protected ServerBootstrap bootstrap = null;
	
	protected abstract ChannelPipeline createPipeline() throws Exception;

	public boolean isStart()  {
		return isStart;
	}
	
	public void setConfig(NettyServerConfig config) {
		this.config = config;
	}

	public NettyServerConfig getConfig() {
		return config;
	}

	public void start()  {
		if (!isStart) {
			try {
				bootstrap = new ServerBootstrap(createChannelFactory());
				bootstrap.setPipelineFactory(createPiplineFactory());
				bootstrap.bind(new InetSocketAddress(config.getPort()));
				
				isStart = true;
				log.info("Netty server start with config: " + JSONObject.toJSONString(config));
			} catch (Exception e) {
				isStart = false;
				bootstrap = null;
				log.error("Netty server start failed: ", e);
			}
		} else {
			log.info("Netty server is already running: " + JSONObject.toJSONString(config));
		}
	}

	public void stop()  {
		if (isStart)  {
			bootstrap.releaseExternalResources();

			isStart = false;
			bootstrap = null;
			log.info("Netty server stop!");
		} else {
			log.info("Netty server is not running!");
		}
	}

	protected ChannelPipelineFactory createPiplineFactory() {
		return new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return createPipeline();
			}
		};
	}

	protected ChannelFactory createChannelFactory() {
		return new NioServerSocketChannelFactory(
				createThreadPool(), 
				createThreadPool(), 
				config.getWorkerCount());
	}

	protected ThreadPoolExecutor createThreadPool() {

		return new ThreadPoolExecutor(
				config.getCorePoolSize(), 
				config.getMaximumPoolSize(), 
				config.getKeepAliveTime(), 
				config.getUnit(), 
				new SynchronousQueue<Runnable>());
	}
}
